﻿using System;
using System.Collections.Generic;
using System.ComponentModel.Composition.Hosting;
using System.ComponentModel.Composition.Primitives;
using System.IO;
using System.Linq;
using System.Reflection;
using Actya.Core.Infrastructure.Logging;

namespace Actya.Core.Infrastructure.Mef
{
	public class PluginDirectoryCatalog : ComposablePartCatalog
	{
		private readonly AggregateCatalog _catalog;
		private readonly ILogger _logger;

		public IEnumerable<Assembly> LoadedAssemblies { get; private set; }

		public PluginDirectoryCatalog(string directory)
		{
			var loadedAssemblies = new List<Assembly>();
			_logger = LogManager.GetLogger(this.GetType());
			var files = Directory.EnumerateFiles(directory, "*.dll", SearchOption.AllDirectories);

			_catalog = new AggregateCatalog();


			foreach (var file in files)
			{
				try
				{
					var assembly = Assembly.LoadFrom(file);
					var asmCat = new AssemblyCatalog(assembly);

					// Force MEF to load the plugin and figure out if there are any exports
					// good assemblies will not throw the RTLE exception and can be added to the catalog
					if (asmCat.Parts.Any())
					{
						_catalog.Catalogs.Add(asmCat);
						loadedAssemblies.Add(assembly);
					}
				}
				catch (ReflectionTypeLoadException ex)
				{
					_logger.Error(ex);
				}
				catch (BadImageFormatException ex)
				{
					_logger.Error(ex);
				}
			}
			this.LoadedAssemblies = loadedAssemblies;
		}

		public override IQueryable<ComposablePartDefinition> Parts
		{
			get { return _catalog.Parts; }
		}
	}
}
